/*
 * Systemprogrammierung
 * Multiplayer-Quiz
 *
 * Client
 *
 * main.c: Hauptprogramm des Clients
 */

#include "command.h"
#include "listener.h"
#include "common/util.h"
#include "gui/gui_interface.h"
#include "gui/libquizgui.a"
#include "common/sockets.h"
#include <sys/types.h> //
#include <getopt.h>
#include <pthread.h>
#include <unistd.h> //optind sollte da drin sein
#include <netdb.h>
#include "common/rfc.h"
#include <stddef.h> //NULL sollte damit eig gelöst sein

#define MAX_NAME_LENGTH (32)

//Prototypen
static int parseCommandline(int argc, char **argv);
void PrintHelp();
int main(int args, char **argv);
void Login(char* name);
extern void HandleError(struct NET_MESSAGE* msg);
void CatalogRequest();

//Variablen
struct ST_GLOBAL_CLIENT_INFO clientInfo;
pthread_t listener_thread_id;
char* port = TCP_DEFAULT_PORT;
char* serverIP = TCP_DEFAULT_HOST;

//Funktionen:

static int parseCommandline(int argc, char **argv) {
	while (optind < argc) {
		int result = getopt(argc, argv, "p:dh:n:");
		if (result == -1)
			return 0; //end of list
		switch (result) {
		case '?':
			fprintf(stderr, "Unbekannter Parameter");
			PrintHelp();
			exit(0);

		case ':':
			fprintf(stderr, "Fehlendes Argument");
			PrintHelp();
			exit(0);

		case 'n':
			clientInfo.name = (char*) optarg;
			break;

		case 'p':
			port = (char*) optarg;
			infoPrint("Manueller Port: = %s", port);
			break;

		case 'h':
			serverIP = (char*) optarg;
			infoPrint("Manueller Host: = %s", serverIP);
			break;

		case 'd':
			debugEnable();
			infoPrint("Debugmodus an");
			break;

		default:
			infoPrint("Fehler Argumentauswertung \n");
			PrintHelp();
			exit(0);
		}
	}
	return 0;
}

int main(int argc, char **argv) {
	int thread;

	//hole Kommandozeilenparameter
	parseCommandline(argc, argv);

	//Namensprüfung
	if (clientInfo.name == NULL) {
		printf("Es wurde kein Name angegeben. Client wird beendet.\n");
		PrintHelp();
		return 0;
	} else if (strlen(clientInfo.name) > MAX_NAME_LENGTH - 1) {
		printf("Name ist zu lang. Client wird beendet.\n");
		return 0;
	}

	setProgName(argv[0]);

	infoPrint("Client Gruppe Wolf, Heissenberger, Buchmaier");

	//Client Socket erstellen
	while (clientInfo.sock == 0) {
		clientInfo.sock = CreateClientSocket(serverIP, port);
	}

	//War der Verbindungsaufbau erfolgreich, dann...
	if (clientInfo.sock <= 0) {
		infoPrint(
				"Es konnte keine Verbindung zum Server hergestellt werden. Client wird beendet.");
	} else {
		//Debug Ausgaben:
		debugPrint("Einloggen...");
		debugPrint("GUI wird initialisiert");

		//Initialisiere GUI
		guiInit(&argc, &argv);
		preparation_showWindow();

		//Loginanfrage senden
		Login(clientInfo.name);

		//alles Ok? Dann Catalog Request
		CatalogRequest();

		//Listener Thread zum empfangen von Nachrichten starten
		thread = pthread_create(&listener_thread_id, NULL, listener_thread,
				(void*) &clientInfo);
		if (thread) {
			printf("Fehler beim starten des Listener Threads\n");
			exit(0);
		}

		//Thread wartet
		guiMain();

		//GUI freigeben
		guiDestroy();
		guiQuit();
	}

	return 0;
}

void PrintHelp() {
	printf("Aufruf: ./client -n NAME\n");
	printf("[-d] [-p PORTNUMMER] [-h SERVERIP]\n");
	printf(
			"Standard für PORT ist: 54321\n Standard für Host IP ist: 127.0.0.1\n");
	exit(0);
}

void Login(char* name) {
	struct NET_MESSAGE senddata;

	senddata = PackRFCMsg(TYPE_IS_LOGIN_REQUEST, strlen(name), name);
	if (SendRFCMsg(clientInfo.sock, &senddata) > 0)
		debugPrint("Login gesendet");
	else {
		debugPrint("Login konnte nicht gesendet gesendet werden");
		guiShowErrorDialog("Login konnte nicht gesendet werden.", 1);
	}

	//Login Response empfangen
	struct NET_MESSAGE recvdata;

	//Fehler beim emfangen
	if (ReceiveRFCMsg(clientInfo.sock, &recvdata) < 0) {
		debugPrint("Fehler beim empfangen des Login Response");
		guiShowErrorDialog("Konnte Login nicht senden", 1);
	}
	//RFC Nachricht wurde empfangen
	else {
		//Auf Headertypen wechseln
		switch (recvdata.header.type) {
		case TYPE_IS_LOGIN_RESPONSE_OK:

			memmove(&clientInfo.ID, recvdata.data, recvdata.header.size);
			break;

		case TYPE_IS_ERROR:

			HandleError(&recvdata);
			break;
		}
	}

	//Speicher freigeben
	SecureFree(recvdata.data);
	recvdata.data = NULL;

	//Spielerrechte für normale Spieler, ohne Spielleiter freigeben
	preparation_setMode(PREPARATION_MODE_NORMAL);
	debugPrint("Login war erfolgreich. Client ID: %d", clientInfo.ID);

	//Bei Spielvorbereitung Spielerrechte für Spielleiter freischalten

}



